/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package coalescent.is.cef.pui.pob;

import cef.pui.pob.Builder;
import cef.pui.pob.BuilderException;
import coalescent.is.Samplers_K69;
import coalescent.statistic.K69_AC;
import commons.core.Duration;
import commons.core.ValueTypes;
import commons.is.Sampler;
import commons.util.TwoWayConverterS;
import commons.util.ValidationUtil;
import commons.util.base.TwoWayConverter;

import javax.xml.bind.PropertyException;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;

import static coalescent.cef.pui.pob.Builders_Coa.of_AC_K69_GT_File;

/**
 * Builder for value type {@code Collection<Sampler<?>>}. The available properties are:
 * <ul>
 *     <li>{@code coalescent.is.ISamplers.gt_EGT = true | false. If true, the properties specified
 *         in } {@link coalescent.cef.pui.pob.Builders_Coa#of_AC_K69_GT_File(java.util.Properties, String)
 *         GeneTree} {@code and } {@link coalescent.cef.pui.pob.Builders_Coa#of_Model_K69(java.util.Properties, String)
 *         K69} {@code need to be present as well.}
 *     </li>
 *     <li>{@code coalescent.is.ISamplers.gt_SD =
 *         true | false. If true, the properties specified in } {@link coalescent.cef.pui.pob.Builders_Coa#of_AC_K69_GT_File(java.util.Properties, String)
 *         GeneTree} {@code and } {@link coalescent.cef.pui.pob.Builders_Coa#of_Model_K69(java.util.Properties, String)
 *         K69} {@code need to be present as well.}
 *     </li>
 *     <li>{@code coalescent.is.ISamplers.gt_Hobolth =
 *         true | false. If true, the properties specified in } {@link coalescent.cef.pui.pob.Builders_Coa#of_AC_K69_GT_File(java.util.Properties, String)
 *         GeneTree} {@code and } {@link coalescent.cef.pui.pob.Builders_Coa#of_Model_K69(java.util.Properties, String)
 *         K69} {@code need to be present as well.}
 *     </li>
 * </ul>
 *
 * @author Susanta Tewari
 * @version version
 * @history Created on Aug 2, 2012.
 * @since since
 */
public class Samplers_Bldr extends Builder<Collection<Sampler<?>>> {

    private static final String propKey_ItrType            = "itrType";
    private static final String ItrType_Options_SampleSize = "sampleSize";
    private static final String ItrType_Options_Time       = "time";

    /** value for the chosen iteration type */
    private static final String propKey_ItrValue = "itrTypeVal";
    private final String acPrefix;

    public Samplers_Bldr(final Properties props, final String prefix, String acPrefix) {

        super(prefix, props);

        this.acPrefix = acPrefix;

        addPropertyKey(Samplers_K69.GT_EGT);
        addPropertyKey(Samplers_K69.GT_SD);
        addPropertyKey(Samplers_K69.GT_HUW);
        addPropertyKey(propKey_ItrType);
        addPropertyKey(propKey_ItrValue);
    }

    @Override
    protected Collection<Sampler<?>> buildFromProps() throws BuilderException {

        final Collection<Sampler<?>> samplers = new ArrayList<>(4);


        // load the computations
        if (loadProp(Samplers_K69.GT_EGT)) samplers.add(of_GT_EGT());
        if (loadProp(Samplers_K69.GT_SD)) samplers.add(of_GT_SD());
        if (loadProp(Samplers_K69.GT_HUW)) samplers.add(of_GT_HUW());


        // itr type
        String itrType    = getProperty(getFullPropertyKey(propKey_ItrType));
        String itrTypeVal = getProperty(getFullPropertyKey(propKey_ItrValue));

        for (Sampler<?> sampler : samplers) {

            switch (itrType) {

                case ItrType_Options_SampleSize :
                    final long sampleSize = Long.parseLong(itrTypeVal);

                    sampler.setIteratorBySampleSize(sampleSize);

                    break;

                case ItrType_Options_Time :
                    final int time = new Duration(itrTypeVal).toMillis();

                    sampler.setIteratorByTime(time);

                    break;

                default :
                    throw new IllegalStateException("invalid iteration type");
            }
        }

        return samplers;
    }


    // <editor-fold desc="Color">
    public Builder<ValueTypes.ColorMap> getColorMapBuilder() {
        return getColorMapBuilder(props, this);
    }

    static Builder<ValueTypes.ColorMap> getColorMapBuilder(final Properties props,
            final Builder<?> b) {

        return new Builder<ValueTypes.ColorMap>(b.getPrefix(), props) {

            @Override
            protected ValueTypes.ColorMap buildFromProps() throws BuilderException {

                ValueTypes.ColorMap map = new ValueTypes.ColorMap();

                addColor(map, Samplers_K69.GT_EGT, b);
                addColor(map, Samplers_K69.GT_SD, b);
                addColor(map, Samplers_K69.GT_HUW, b);
                addColor(map, Samplers_K69.EXACT, b);

                return map;
            }
            @Override
            public String getBuilderString() {
                return "Undefined";
            }
        };
    }

    private static void addColor(ValueTypes.ColorMap map, String label, final Builder<?> b) {

        final TwoWayConverter<String, Color> cnv = TwoWayConverterS.ofColor(",");
        final String colorKey                    = label + "-" + "Color";

        if (loadColorProp(label, b)) {

            final String colorVal = b.getPropertyX(colorKey);

            if ((colorVal != null) &&!colorVal.isEmpty()) {
                map.addColor(label, cnv.fwd(colorVal));
            }
        }
    }

    private static boolean loadColorProp(String colorKey, Builder<?> b) {
        return b.getPropertyX(colorKey) != null;
    }    // </editor-fold>

    @Override
    public String getBuilderString() {
        return "NotYetNecessary";
    }

    protected boolean loadProp(final String prop) throws BuilderException {

        final String propertyKey = getFullPropertyKey(prop);
        final String propVal     = getProperty(propertyKey);

        if (propVal == null) return false;

        try {
            ValidationUtil.validateProperty(propertyKey, getProperty(propertyKey));
        } catch (PropertyException ex) {
            throw new BuilderException("Invalid property for Samplers_Bldr", ex);
        }

        final boolean result;

        try {
            result = Boolean.parseBoolean(getProperty(propertyKey));
        } catch (NumberFormatException ex) {
            throw new BuilderException("", ex);
        }

        return result;
    }

    private Sampler<?> of_GT_EGT() {

        final Builder<K69_AC> bldr = of_AC_K69_GT_File(props, acPrefix);

        return Samplers_K69.of_GT_EGT(bldr.build(), 500);
    }

    private Sampler<?> of_GT_SD() {

        final Builder<K69_AC> bldr = of_AC_K69_GT_File(props, acPrefix);

        return Samplers_K69.of_GT_SD(bldr.build(), 500);
    }

    private Sampler<?> of_GT_HUW() {

        final Builder<K69_AC> bldr = of_AC_K69_GT_File(props, acPrefix);

        return Samplers_K69.of_GT_HUW(bldr.build(), 500);
    }
}
